function draw_box_scatter(data, ctrls, groupdesc) {
	
	max = d3.max(data.map(function(reps){return d3.max(reps.map(function(d){return d3.max(d[1]);}))}))
	min = d3.min(data.map(function(reps){return d3.min(reps.map(function(d){return d3.min(d[1]);}))}))
	
	//min = d3.min(data.map(function(d){return d3.min(d[1]);}))
	//max = d3.min(data.map(function(d){return d3.min(d[1]);}))
	
	// the ids for constructing urls to open plate page	
	plateids=[]
	data.forEach(function(d){for(i=0;i<d.length;i++){plateids.push(d[i][2])}})

	var chart = d3.box()
		.whiskers(iqr(1.5))
		.height(height)	
		.domain([min, max])
		.showLabels(labels);


	var svg_parent = d3.select("body").append("svg")
		.attr("width", width + margin.left + margin.right)
		.attr("height", height + margin.top*2 + margin.bottom)
		.attr("class", "box")    
	var svg = svg_parent
		.append("g")
		.attr("transform", "translate(" + margin.left + "," + margin.top + ")");



	// the x-axis
	var x = d3.scale.ordinal()	   
		.domain(
				data.map(function(reps) { return reps.map(function(d){return d[0]}) } )
			        .reduce(function(a,b){return a.concat(b)})	
		       )	    
		.rangeRoundBands([0 , width], 0.7, 0.3); 		

	var xAxis = d3.svg.axis()
		.scale(x)
		.orient("bottom");

	// the y-axis
	var y = d3.scale.linear()
		.domain([min, max])
		.range([height + margin.top, 0 + margin.top]);
	
	var yAxis = d3.svg.axis()
    .scale(y)
    .orient("left");


	// flatten the list of Data points group by platename i.e all replicates per plate
	data_flat = data.reduce(function(a,b){return a.concat(b)});
	
	// draw the boxplots	
	svg.selectAll(".box")	   
      .data(data_flat)
	  .enter().append("g")
		.attr("transform", function(d) { return "translate(" +  x(d[0])  + "," + margin.top + ")"; } )
      .call(chart.width(x.rangeBand())); 


// draw the dots
box_w=x.rangeBand()
for (i=0; i<data.length; i++)	{
	
	for(j=0; j<data[i].length; j++){
	xpos=data[i][j][0];
	index=i;
	offset = j
	  

	//############ Filter out NaN ############
	filtered=data[i][j][1].filter(function(d) {return d;})
	var arr_data = []
	for (c=0; c<filtered.length; c++){
		arr_data.push({'ind':index, 'dat':filtered[c]})
	}

	// offset the dots to make reps closer together
	if (offset==0){ dx=x.rangeBand()/2}
	else {dx=-x.rangeBand()/4}

	svg.selectAll(".dot").data(arr_data).enter()
	.append("circle")
	.attr("cy", function(d, i) { return y(d.dat);})
	.attr("cx", function(d, i) { return x(xpos) + box_w/2 + (Math.random()*2-1)*box_w/4 +dx;})
	.attr("r", 3)
	.attr("class", "pair"+index)
	.on("mouseover", function(d, i) {
			/*	
		  tooltip.transition()
		       .duration(100)
		       .style("opacity", .9);
		  tooltip.html(data_labels[i]+"<br/> "+d.dat)
		       .style("left", (d3.event.pageX + 5) + "px")
		       .style("top", (d3.event.pageY - 28) + "px");
			*/	
		nohighlight=".pair"+d.ind
		d3.selectAll(nohighlight)
		.attr("class", "highlighted");
		
	      })
	      .on("mouseout", function(d) {

		d3.selectAll('.highlighted')
		.attr("class", "pair"+d.ind);

			/*	
		  tooltip.transition()
		       .duration(500)
		       .style("opacity", 0);
			*/	
	     }).on("click", function(d) {
			//drawScatter(data[d.ind], scatterplot, offset);
			//
			

			obj_arr=replsToArray(data[d.ind], ctrls)	
			drawScatterMatrix(obj_arr, ctrls);
				         });
	      
	      
	}

	}
	
	      
	// add a title
	svg.append("text")
        .attr("x", (width / 2))             
        .attr("y", 0 + (margin.top / 2))
        .attr("text-anchor", "middle")  
        .style("font-size", "18px") 
        //.style("text-decoration", "underline")  
        .text(groupdesc);

	svg.append("text")
        .attr("x", (width / 2))             
        .attr("y", height + (margin.bottom))
        .attr("text-anchor", "middle")  
        .style("font-size", "18px") 
        .style("fill", "green") 
        .text("Click on platenames to go to plate");

	 // draw y axis
	svg.append("g")
        .attr("class", "y axis")
        .call(yAxis)
		.append("text") // and text1
		  .attr("transform", "rotate(-90)")
		  .attr("y", 6)
		  .attr("dy", ".71em")
		  .style("text-anchor", "end")
		  .style("font-size", "12px") 
		  .text("Raw readout");		
	
	// draw x axis	
	svg.append("g")
      .attr("class", "x axis platename")
      .attr("transform", "translate(0," + (height  + margin.top + 10) + ")")
      .call(xAxis)
	.selectAll("text")
    .attr("y", 0)
    .attr("x", 9)
    .attr("dy", ".35em")
    .attr("transform", "rotate(90)")
    .style("text-anchor", "start");

	// click to go to plate page	
	d3.select('.x.axis.platename').selectAll('.tick.major')
	.on('click', function(d, i){
			window.open("//" + "127.0.0.1:8000/p/"+plateids[i])
	});




}


function replsToArray(data, ctrls){
	obj_arr=[]

	// loop through data points
	for(i=0;i<data[0][1].length;i++){
		obj={}	
		// loop through replicas
		for(j=0;j<data.length;j++){
			obj[data[j][0]]=data[j][1][i]
		}

		if(data_labels[i] in ctrls)
		{
		obj['well_type']=ctrls[data_labels[i]].type
		}
		else{obj['well_type']=''}
		
		obj_arr.push(obj)
	}
	return obj_arr
}



function drawScatterMatrix(data, ctrls) {

var width = 960,
    size = 550,
    padding = 30;

var x = d3.scale.linear()
    .range([padding / 2, size - padding / 2]);

var y = d3.scale.linear()
    .range([size - padding / 2, padding / 2]);

var xAxis = d3.svg.axis()
    .scale(x)
    .orient("bottom")
    .ticks(5)
    .tickFormat(d3.format("s"));

var yAxis = d3.svg.axis()
    .scale(y)
    .orient("left")
    .ticks(5)
    .tickFormat(d3.format("s"));

//var color = d3.scale.category10();
  
var ctrl_cmap={'pos':'red',
	       'nt':'black',
	       'untreated':'green',
	       'nontarg':'gold',
	       'other':'yellow'
    }

var domainByTrait = {},
      traits = d3.keys(data[0]).filter(function(d) { return d !== "well_type"; }),
      n = traits.length;

  traits.forEach(function(trait) {
    domainByTrait[trait] = d3.extent(data, function(d) { return d[trait]; });
  });

  xAxis.tickSize(size * n);
  yAxis.tickSize(-size * n);

  var brush = d3.svg.brush()
      .x(x)
      .y(y)
      .on("brushstart", brushstart)
      .on("brush", brushmove)
      .on("brushend", brushend);

  if(d3.select('svg#scatter_matrix')[0][0]!=null) 
  {d3.select('svg#scatter_matrix')[0][0].remove()}

  var svg = d3.select("body").append("svg")
	.attr("id", "scatter_matrix")
      .attr("width", size * n + padding)
      .attr("height", size * n + padding)
    .append("g")
      .attr("transform", "translate(" + padding + "," + padding / 2 + ")");

  svg.selectAll(".x.axis")
      .data(traits)
    .enter().append("g")
      .attr("class", "x axis")
      .attr("transform", function(d, i) { return "translate(" + (n - i - 1) * size + ",0)"; })
      .each(function(d) { x.domain(domainByTrait[d]); d3.select(this).call(xAxis); });

  svg.selectAll(".y.axis")
      .data(traits)
    .enter().append("g")
      .attr("class", "y axis")
      .attr("transform", function(d, i) { return "translate(0," + i * size + ")"; })
      .each(function(d) { y.domain(domainByTrait[d]); d3.select(this).call(yAxis); });

  var cell = svg.selectAll(".cell")
      .data(cross(traits, traits))
    .enter().append("g")
      .attr("class", "cell")
      .attr("transform", function(d) { return "translate(" + (n - d.i - 1) * size + "," + d.j * size + ")"; })
      .each(plot);

  function plot(p) {
    var cell = d3.select(this);

    x.domain(domainByTrait[p.x]);
    y.domain(domainByTrait[p.y]);

    cell.append("rect")
        .attr("class", "frame")
        .attr("x", padding / 2)
        .attr("y", padding / 2)
        .attr("width", size - padding)
        .attr("height", size - padding);

    cell.selectAll("circle")
        .data(data)
      .enter().append("circle")
        .attr("cx", function(d) { return x(d[p.x]); })
        .attr("cy", function(d) { return y(d[p.y]); })
        .attr("r", 3)
	.on("mouseover", function(d, i) {
		  d3.select(this).transition().duration(10).attr("r", 5);

		  tooltip.transition()
		       .duration(100)
		       .style("opacity", .9);
		  tooltip.html(data_labels[i]+"<br/> "+d[p.x]+"<br/> "+
			  d[p.y])
		       .style("left", (d3.event.pageX + 5) + "px")
		       .style("top", (d3.event.pageY - 28) + "px");
	      })
	      .on("mouseout", function(d) {
		  d3.select(this).transition().duration(10).attr("r", 3);

		  tooltip.transition()
		       .duration(500)
		       .style("opacity", 0);})
        .style("fill", function(d) { 
		return ctrl_cmap[d.well_type]; });
  }


  // draw control type legend
  all_types=Object.keys(ctrls).map(function(k){return ctrls[k].type}).sort() 
  types=[]
  for(i=0;i<all_types.length;i++){if(types.indexOf(all_types[i])<0){types.push(all_types[i])}}
  
  colors=[]
  for(k=0; k<types.length; k++){
  colors.push({'type':types[k], 'color':ctrl_cmap[types[k]]})
  }


	title = Object.keys(data[0]).filter(function(n){if(n!="well_type" && n!="label"){
	return n}}).join(' vs ')

	svg.append("text")
        .attr("x", (width / 2 + padding))             
        .attr("y", 0 )
        .attr("text-anchor", "middle")  
        .style("font-size", "18px") 
        //.style("text-decoration", "underline")  
        .text(title);
 

  var legend = svg.selectAll(".legend")
      .data(colors)
    .enter().append("g")
      .attr("class", "legend")
      .attr("transform", function(d, i) { return "translate(0," + i * 20 + ")"; });

  // draw legend colored rectangles
  legend.append("rect")
      .attr("x", 44)
      .attr("width", 18)
      .attr("height", 18)
      .style("fill", function(d){return d.color});

  // draw legend text
  legend.append("text")
      .attr("x", 38)
      .attr("y", 9)
      .attr("dy", ".35em")
      .style("text-anchor", "end")
      .text(function(d) { return d.type;})

  // Titles for the diagonal.
  cell.filter(function(d) { return d.i === d.j; }).append("text")
      .attr("x", padding)
      .attr("y", padding)
      .attr("dy", ".71em")
      .html(function(d) { return d.x; });










  //cell.call(brush);
  var brushCell;

  // Clear the previously-active brush, if any.
  function brushstart(p) {
    if (brushCell !== this) {
      d3.select(brushCell).call(brush.clear());
      x.domain(domainByTrait[p.x]);
      y.domain(domainByTrait[p.y]);
      brushCell = this;
    }
  }

  // Highlight the selected circles.
  function brushmove(p) {
    var e = brush.extent();
    svg.selectAll("circle").classed("hidden", function(d) {
      return e[0][0] > d[p.x] || d[p.x] > e[1][0]
          || e[0][1] > d[p.y] || d[p.y] > e[1][1];
    });
  }

  // If the brush is empty, select all circles.
  function brushend() {
    if (brush.empty()) svg.selectAll(".hidden").classed("hidden", false);
  }

  function cross(a, b) {
    var c = [], n = a.length, m = b.length, i, j;
    for (i = -1; ++i < n;) for (j = -1; ++j < m;) c.push({x: a[i], i: i, y: b[j], j: j});
    return c;
  }

  d3.select(self.frameElement).style("height", size * n + padding + 20 + "px");
}



// Returns a function to compute the interquartile range.
function iqr(k) {
  return function(d, i) {
    var q1 = d.quartiles[0],
        q3 = d.quartiles[2],
        iqr = (q3 - q1) * k,
        i = -1,
        j = d.length;
    while (d[++i] < q1 - iqr);
    while (d[--j] > q3 + iqr);
    return [i, j];
  };
}
